/*
 * Copyright (c) 2014-2015 Luca Agostini, Alessandro Cantini, Alessandro Dignani
 *
 * This file is part of MeteoCal.
 *
 * MeteoCal is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package it.polimi.se2.agostini_cantini_dignani.meteocal.gui;

import it.polimi.se2.agostini_cantini_dignani.meteocal.business.EventManager;
import it.polimi.se2.agostini_cantini_dignani.meteocal.business.NotificationManager;
import it.polimi.se2.agostini_cantini_dignani.meteocal.business.UserManager;
import it.polimi.se2.agostini_cantini_dignani.meteocal.business.WeatherForecastManager;
import it.polimi.se2.agostini_cantini_dignani.meteocal.entity.Event;
import it.polimi.se2.agostini_cantini_dignani.meteocal.entity.Notification;
import it.polimi.se2.agostini_cantini_dignani.meteocal.entity.User;
import it.polimi.se2.agostini_cantini_dignani.meteocal.model.NotificationType;
import org.primefaces.context.RequestContext;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author Alessandro Cantini
 */
@Named
@SessionScoped
public class NotificationBean extends DateTimeBean {

	@EJB
	private NotificationManager nm;

	@EJB
	private UserManager um;

	@EJB
	private EventManager em;

	@EJB
	private WeatherForecastManager wfm;

	private User user;
	private Map<Notification, Date> alternativeDates;
	private Notification currentNotification;

	@PostConstruct
	public void init() {
		super.init();
		user = um.getLoggedUser();

		alternativeDates = new HashMap<>();
		for (Notification n : user.getNotifications()) {
			if (n.getType() == NotificationType.WEATHER) {
				if (user.equals(n.getEvent().getOwner())) {
					Date alternative = wfm.findAlternativeDate(n.getEvent());
					alternativeDates.put(n, alternative);
				} else {
					alternativeDates.put(n, null);
				}
			}
		}
	}

	public String removeNotificationAction(Notification notification) {
		nm.removeNotification(notification);
		return null;
	}

	public String declineInvitationAction(Notification notification) {
		em.declineInvitation(user, notification.getEvent());
		nm.removeNotification(notification);
		return null;
	}

	public Date getAlternativeDate(Notification notification) {
		if (notification.getType() != NotificationType.WEATHER) {
			return null;
		}
		return alternativeDates.get(notification);
	}

	public String saveAction() {
		if (currentNotification.getType() == NotificationType.INVITATION) {
			return acceptInvitationAction(currentNotification);
		} else {
			assert currentNotification.getType() == NotificationType.WEATHER;
			return acceptDateChange(currentNotification);
		}
	}

	public String showConfirmationDialog(Notification notification) {
		currentNotification = notification;

		Event eventToCheck;
		if (currentNotification.getType() == NotificationType.INVITATION) {
			eventToCheck = notification.getEvent();
		} else {
			assert currentNotification.getType() == NotificationType.WEATHER;
			eventToCheck = new Event();
			eventToCheck.setStartTime(getAlternativeDate(currentNotification));
			eventToCheck.setEndTime(new Date(eventToCheck.getStartTime().getTime() + notification.getEvent().duration()));
		}

		if (em.thereAreOverlappingEvents(eventToCheck, user.getCalendar())) {
			RequestContext.getCurrentInstance().execute("PF('notificationsConfirmDialog').show()");
			return null;
		}
		return saveAction();
	}

	public User getUser() {
		return um.getLoggedUser();
	}

	private String acceptInvitationAction(Notification notification) {
		em.acceptInvitation(user, notification.getEvent());
		nm.removeNotification(notification);
		return null;
	}

	private String acceptDateChange(Notification notification) {
		em.moveEvent(notification.getEvent(), alternativeDates.get(notification));
		nm.removeNotification(notification);
		return null;
	}
}
